package cn.seaboot.excel.sax;

import cn.seaboot.commons.file.IOUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

/**
 *
 *
 * @author Mr.css
 * @version 2025-06-30 17:20
 */
public class XmlToExcel {

    private ExcelContext context;

    private final TableHeadParser tableHeadParser = new TableHeadParser();
    private final TableRowParser tableRowParser = new TableRowParser();
    private final TableCellParser tableCellParser = new TableCellParser();

    public XmlToExcel() {
        tableRowParser.setTableCellParser(tableCellParser);
        tableHeadParser.setTableRowParser(tableRowParser);
    }

    /**
     * 数据映射
     *
     * @param is      输入流
     * @param context 指定的 excel 上下文
     * @throws IOException       -
     * @throws DocumentException -
     */
    private void parse(InputStream is, ExcelContext context) throws IOException, DocumentException {
        this.context = context;

        tableRowParser.setContext(context);
        tableCellParser.setContext(context);

        SAXReader reader = new SAXReader();
        Document document = reader.read(is);

        Element table = document.getRootElement();

        this.parseTable(table);
    }


    /**
     * 读取 table 内容
     *
     * @param table 表格
     */
    public void parseTable(@NotNull Element table) throws IOException {
        for (Element ele : table.elements()) {
            String name = ele.getName();
            if ("tr".equals(name)) {
                this.parseRow(ele);
            } else if ("thead".equals(name)) {
                tableHeadParser.parse(ele);
            } else if ("tbody".equals(name)) {
                parseTableBody(ele);
            } else if ("tfoot".equals(name)) {
                tableHeadParser.parse(ele);
            } else {
                throw new IllegalArgumentException("illegal element: " + name);
            }
        }
    }

    /**
     * 重写单元格处理程序
     *
     * @param tbody -
     */
    public void parseTableBody(Element tbody) {
        List<Element> trs = tbody.elements();
        for (Element tr : trs) {
            this.parseRow(tr);
        }
    }


    /**
     * 处理一行数据
     *
     * @param tr 表格行
     */
    public void parseRow(Element tr) {
        // next line
        context.nextLine();

        // 处理单元格内的数据
        List<Element> cells = tr.elements();
        for (Element cell : cells) {
            context.nextCell().setCellValue(cell.getText());
        }
    }

    public static void main(String[] args) throws IOException, DocumentException {
        String file = "C:\\Users\\ASUS\\Desktop\\table.xml";

        try (Workbook workbook = new XSSFWorkbook()) {
            Sheet sheet = workbook.createSheet();

            ExcelContext context = new ExcelContext();
            context.setSheet(sheet);

            XmlToExcel xmlToExcel = new XmlToExcel();

            try (InputStream is = IOUtils.openFileInputStream(file)) {
                xmlToExcel.parse(is, context);
            }

            try (OutputStream os = IOUtils.openFileOutputStream("C:\\Users\\ASUS\\Desktop\\ret.xlsx")) {
                workbook.write(os);
            }
        }
    }
}
